﻿using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Windows;

using TimeSpan.Views;
using TimeSpan.Views.Dialogs;
using TimeSpan.Views.Pages;

namespace TimeSpan.Services;

public class WorkflowService {

    /// <summary>
    /// 工作流：新建任务。
    /// <br /> 接收 无
    /// <br /> 输出 <see cref="SpanTaskOption"/>
    /// <br /> 结果发送至工作流 <see cref="PreStartTask"/>
    /// </summary>
    public Subject<object?> NewTask { get; } = new();

    /// <summary>
    /// 工作流：预启动任务。
    /// <br /> 接收 <see cref="SpanTaskOption"/>
    /// <br /> 输出 <see cref="SpanTask"/>，<see cref="bool"/>?
    /// <br /> <see langword="true"/> -> 结果发送至工作流 <see cref="StartTask"/>
    /// <br /> <see langword="false"/> -> 编辑结果后重新发送至此工作流
    /// <br /> <see langword="null"/> -> 结果忽略
    /// </summary>
    public Subject<SpanTaskOption> PreStartTask { get; } = new();

    /// <summary>
    /// 工作流：添加或编辑任务。
    /// <br /> 接收 <see cref="SpanTaskOption"/>?（null 为添加，否则为编辑）
    /// <br /> 保存
    /// </summary>
    public Subject<SpanTaskOption?> AddOrEditTaskOption { get; } = new();

    /// <summary>
    /// 工作流：删除任务。
    /// <br /> 接收 <see cref="SpanTaskOption"/>
    /// <br /> 保存
    /// </summary>
    public Subject<SpanTaskOption> DeleteTaskOption { get; } = new();

    /// <summary>
    /// 工作流：添加或编辑便笺。
    /// <br /> 接收 <see cref="Note"/>?（null 为添加，否则为编辑）
    /// <br /> 保存
    /// </summary>
    public Subject<Note?> AddOrEditNote { get; } = new();

    /// <summary>
    /// 工作流：删除便笺。
    /// <br /> 接收 <see cref="Note"/>
    /// <br /> 保存
    /// </summary>
    public Subject<Note> DeleteNote { get; } = new();

    /// <summary>
    /// 工作流：启动任务。
    /// <br /> 接收 <see cref="SpanTask"/>
    /// </summary>
    public Subject<SpanTask> StartTask { get; } = new();

    /// <summary>
    /// 工作流：结算任务。
    /// <br /> 接收一个运行完的 <see cref="SpanTask"/>
    /// </summary>
    public Subject<SpanTask> SettleTask { get; } = new();

    /// <summary>
    /// 工作流：删除任务记录。
    /// <br /> 接收一个 <see cref="TaskRecord"/>
    /// </summary>
    public Subject<TaskRecord> DeleteTaskRecord { get; } = new();

    public WorkflowService(
        IDialogService dialog,
        IMessageService message,
        INavigationService navigation,
        IConfig<SpanTasksConfig> optionsConfig,
        IConfig<NotesConfig> notesConfig,
        IConfig<TaskRecordsConfig> recordsConfig) {

        async void SaveConfig<T>(IConfig<T> config) where T : class, new() {
            await config.SaveAsync();
            await message.MessageAsync("保存成功");
        }

        NewTask
            .Select(_ => dialog.EditWithDialog<SpanTaskOption, NewRecordWindow>())!
            .OfType<SpanTaskOption>()
            .Do(PreStartTask.OnNext)
            .Subscribe();

        PreStartTask
            .Select(x => new { Option = x, Task = new SpanTask(x) })
            .Select(x => new { Result = dialog.GetDialogResult<SpanTask, SpanResultWindow, bool?>(x.Task), Data = x })
            .Do(x => {
                if (x.Result == true) {
                    StartTask.OnNext(x.Data.Task);
                } else if (x.Result == false) {
                    if (dialog.EditWithDialog<SpanTaskOption, NewPresetWindow>(x.Data.Option) is SpanTaskOption option) {
                        PreStartTask.OnNext(option);
                    }
                } else { }
            })
            .Subscribe();

        // 添加
        AddOrEditTaskOption
            .Where(x => x == null)
            .Select(_ => dialog.EditWithDialog<SpanTaskOption, NewPresetWindow>())!
            .OfType<SpanTaskOption>()
            .Do(optionsConfig.Config.Add)
            .Do(_ => SaveConfig(optionsConfig))
            .Subscribe();

        // 编辑
        AddOrEditTaskOption!
            .OfType<SpanTaskOption>()
            .Select(x => new { Result = dialog.EditWithDialog<SpanTaskOption, NewPresetWindow>(x), Data = x })
            .Where(x => x.Result != null)
            .Do(x => optionsConfig.Config.Replace(x.Data, x.Result!))
            .Do(_ => SaveConfig(optionsConfig))
            .Subscribe();

        DeleteTaskOption
            .Where(_ => message.ConfirmAsync("确认删除").Result)
            .Do(optionsConfig.Config.Delete)
            .Do(_ => SaveConfig(optionsConfig))
            .Subscribe();

        // 添加
        AddOrEditNote
            .Where(x => x == null)
            .Select(_ => dialog.EditWithDialog<Note, NoteEditWindow>())!
            .OfType<Note>()
            .Do(notesConfig.Config.Notes.Add)
            .Do(_ => SaveConfig(notesConfig))
            .Subscribe();

        // 编辑
        AddOrEditNote!
            .OfType<Note>()
            .Select(x => new { Result = dialog.EditWithDialog<Note, NoteEditWindow>(x), Data = x })
            .Where(x => x.Result != null)
            .Do(x => notesConfig.Config.Notes.Replace(x.Data, x.Result!))
            .Do(_ => SaveConfig(notesConfig))
            .Subscribe();

        DeleteNote
            .Where(_ => message.ConfirmAsync("确认删除").Result)
            .Do(x => notesConfig.Config.Notes.Remove(x))
            .Do(_ => SaveConfig(notesConfig))
            .Subscribe();

        StartTask
            .Do(x => x.PrepareToStart())
            .Do(navigation.Navigate<RuntimePage>)
            .Subscribe();

        SettleTask
            .Do(x => dialog.DisplayDialog<SpanTask, SettleWindow>(x))!
            .Select(x => new TaskRecord() { Title = x.Title, TotalDuartion = x.FinishBlocksTotalMinutes })
            .Do(x => recordsConfig.Config.TaskRecords = [.. recordsConfig.Config.TaskRecords, x])
            .Do(_ => SaveConfig(recordsConfig))
            .Subscribe();

        DeleteTaskRecord
            .Do(x => recordsConfig.Config.TaskRecords = [.. recordsConfig.Config.TaskRecords.Except([x])])
            .Do(_ => SaveConfig(recordsConfig))
            .Subscribe();

    }

}